import os
import pydicom as dcm
from pydicom.fileset import FileSet
from pydicom import config
import warnings


def safe_get(element, default=""):
    """安全获取DICOM元素值的通用方法"""
    try:
        value = element.value
        if isinstance(value, (dcm.valuerep.PersonName, dcm.valuerep.IS)):
            return str(value)
        return value
    except (AttributeError, KeyError):
        return default


def decode_dicom_element(element):
    """增强型DICOM元素解码"""
    raw_value = safe_get(element)

    # 处理不同类型的数据
    if isinstance(raw_value, list):
        return [decode_dicom_item(item) for item in raw_value]
    return decode_dicom_item(raw_value)


def decode_dicom_item(item):
    """增强解码逻辑处理边缘情况 """
    if isinstance(item, bytes):
        # 尝试去除可能的空字节
        clean_bytes = item.strip(b'\x00')

        # 优先尝试DICOM默认编码
        try:
            return clean_bytes.decode('latin1').replace('\\', os.sep)
        except UnicodeDecodeError:
            pass

        # 中文编码检测
        encodings = ['gb18030', 'gbk', 'utf-8']
        for enc in encodings:
            try:
                return clean_bytes.decode(enc).replace('\\', os.sep)
            except UnicodeDecodeError:
                continue

        # 最终回退方案
        return clean_bytes.decode('latin1', errors='replace')

    elif isinstance(item, (dcm.valuerep.IS, dcm.valuerep.DSfloat)):
        return str(item)
    return str(item)


def parse_dicomdir(dicomdir_path):
    """强化版DICOMDIR解析"""
    print(f"\n=== 解析DICOMDIR: {dicomdir_path} ===")

    if not os.path.exists(dicomdir_path):
        print("× 文件不存在")
        return

    config.enforce_valid_values = False
    warnings.filterwarnings("ignore", category=UserWarning)

    try:
        dataset = dcm.dcmread(dicomdir_path)
        print("√ DICOM文件头解析成功")
    except Exception as e:
        print(f"× 文件读取失败: {str(e)}")
        return

    # 获取目录记录序列
    records = getattr(dataset, 'DirectoryRecordSequence', [])
    if not records:
        print("! 目录记录序列为空")
        return

    base_dir = os.path.dirname(dicomdir_path)
    existing_files = {f.lower(): f for f in os.listdir(base_dir) if f.lower().endswith('.dcm')}

    current_context = {
        'PatientID': '',
        'StudyInstanceUID': '',
        'SeriesInstanceUID': ''
    }

    for record in records:
        try:
            # 使用新的安全访问方式
            rec_type = decode_dicom_element(record.get((0x0004, 0x1430), ''))

            if rec_type == 'PATIENT':
                current_context['PatientID'] = decode_dicom_element(record.get((0x0010, 0x0020), ''))
                patient_name = decode_dicom_element(record.get((0x0010, 0x0010), '未知'))
                print(f"\n患者: {patient_name} [ID: {current_context['PatientID']}]")

            elif rec_type == 'STUDY':
                current_context['StudyInstanceUID'] = decode_dicom_element(record.get((0x0020, 0x000D), ''))
                study_date = decode_dicom_element(record.get((0x0008, 0x0020), '未知日期'))
                print(f"  检查: {study_date} [UID: {current_context['StudyInstanceUID'][:12]}...]")

            elif rec_type == 'SERIES':
                current_context['SeriesInstanceUID'] = decode_dicom_element(record.get((0x0020, 0x000E), ''))
                series_num = decode_dicom_element(record.get((0x0020, 0x0011), '未知'))

            elif rec_type == 'IMAGE':
                ref_element = record.get((0x0004, 0x1500))
                if ref_element:
                    print(f"\n[DEBUG] ReferencedFileID原始值: {ref_element.value}")  # 显示原始二进制值
                    ref_path = []
                    for idx, part in enumerate(ref_element.value):
                        # 获取原始字节
                        raw_bytes = part.original_string if hasattr(part, 'original_string') else bytes(part)
                        print(f"  Part {idx + 1} 原始字节: {raw_bytes}")  # 显示每个路径组件的字节

                        # 解码处理
                        decoded = decode_dicom_item(raw_bytes)
                        print(f"  Part {idx + 1} 解码结果: {decoded}")
                        ref_path.append(decoded)

                    full_path = os.path.join(*ref_path)
                    print(f"  拼接路径: {full_path}")  # 显示完整路径
                    filename = os.path.basename(full_path).split('?')[0]

        except Exception as e:
            print(f"! 记录解析异常: {str(e)}")
            continue


if __name__ == "__main__":
    dicomdir_path = r"E:\1d\DICOMDIR"
    parse_dicomdir(dicomdir_path)
